package com.szl.group.utils;


import com.szl.group.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;

import java.text.SimpleDateFormat;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.szl.group.common.enums.ResultCodeEnum.*;

/**
 * description: 断言工具类
 * author: shenxiaolong
 * date: 2020/6/20  18:57
 */
public class Assert {

    public final static String PHONE_REG = "^1[3456789]\\d{9}$";
    private final static String EMAIL_REG = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$";
    public final static String IDCARD_REG = "^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$|^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9]|X)$";
    private final static String SPECIAL_WORD_REG = "[ _`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]|\\n|\\r|\\t";
    private final static String CHINESE_WORD_REG = "^[\\u4e00-\\u9fa5]+$";



    /**
     * 断言是否为真，如果为 {@code false} 抛出 {@code MyException} 异常<br>
     *
     * <pre class="code">
     * Assert.isTrue(i &gt; 0, "The value must be greater than zero");
     * </pre>
     *
     * @param expression 波尔值
     * @param errorMsg   错误抛出异常附带的消息模板
     */
    public static void isTrue(boolean expression, String errorMsg) {
        if (!expression) {
            throw new BusinessException(METHOD_ARGUMENT_NOT_VALID.getCode(), errorMsg);
        }
    }

    /**
     * 断言是否为假，如果为 {@code true} 抛出 {@code BusinessException} 异常<br>
     *
     * <pre class="code">
     * Assert.isFalse(i &lt; 0, "The value must be greater than zero");
     * </pre>
     *
     * @param expression 波尔值
     * @param errorMsg   错误抛出异常附带的消息模板
     */
    public static void isFalse(boolean expression, String errorMsg) {
        if (expression) {
            throw new BusinessException(METHOD_ARGUMENT_NOT_VALID.getCode(), errorMsg);
        }
    }

    /**
     * 断言对象是否为{@code null} ，如果不为{@code null} 抛出{@link IllegalArgumentException} 异常
     *
     * <pre class="code">
     * Assert.isNull(value, "The value must be null");
     * </pre>
     *
     * @param object   被检查的对象
     * @param errorMsg 消息模板
     */
    public static void isNull(Object object, String errorMsg) {
        if (object == null) {
            throw new BusinessException(METHOD_ARGUMENT_NOT_VALID.getCode(), errorMsg);
        }
    }

    // ----------------------------------------------------------------------------------------------------------- Check empty

    /**
     * 检查给定字符串是否为空，为空抛出 {@link BusinessException}
     *
     * <pre class="code">
     * Assert.notEmpty(name, "Name must not be empty");
     * </pre>
     *
     * @param text     被检查字符串
     * @param errorMsg 错误消息模板
     * @return 非空字符串
     */
    public static String notEmpty(String text, String errorMsg) {
        if (StringUtils.isEmpty(text)) {
            throw new BusinessException(METHOD_ARGUMENT_NOT_VALID.getCode(), errorMsg);
        }
        return StringUtils.trim(text);
    }

    /**
     * 检查给定字符串是否为空白（null、空串或只包含空白符），为空抛出 {@link BusinessException}
     *
     * <pre class="code">
     * Assert.notBlank(name, "Name must not be blank");
     * </pre>
     *
     * @param text     被检查字符串
     * @param errorMsg 错误消息模板
     * @return 非空字符串
     */
    public static String notBlank(String text, String errorMsg) {
        if (StringUtils.isBlank(text)) {
            throw new BusinessException(METHOD_ARGUMENT_NOT_VALID.getCode(), errorMsg);
        }
        return StringUtils.trim(text);
    }

    /**
     * 检查字符串是不是yyyy-MM-dd时间格式字符串
     *
     * @param text 被检查字符串
     * @return 非空字符串
     */
    public static boolean isDateStr(String text, String pattern, String errorMsg) {

        SimpleDateFormat format = new SimpleDateFormat(pattern);
        try {
            format.parse(text);
            return true;
        } catch (Exception e) {
            throw new BusinessException(METHOD_ARGUMENT_NOT_VALID.getCode(), errorMsg);
        }
    }

    public static void isPage(Integer page, String errorMsg) {
        if (page == null || page < 0) {
            throw new BusinessException(METHOD_ARGUMENT_NOT_VALID.getCode(), errorMsg);
        }
    }

    public static void isPage(Integer page) {
        isPage(page, "分页格式不对");
    }

    public static void isPhoneNum(String phoneNum) {
        if (StringUtils.isBlank(phoneNum) || !phoneNum.matches(PHONE_REG)) {
            throw new BusinessException(METHOD_ARGUMENT_NOT_VALID.getCode(), "手机号格式不正确");
        }
    }

    public static void isEmail(String email) {
        if (StringUtils.isBlank(email) || !email.matches(EMAIL_REG)) {
            throw new BusinessException(METHOD_ARGUMENT_NOT_VALID.getCode(), "email格式不正确");
        }
    }

    public static void isIdCard(String idCard) {
        if (StringUtils.isBlank(idCard) || !idCard.matches(IDCARD_REG)) {
            throw new BusinessException(METHOD_ARGUMENT_NOT_VALID.getCode(), "身份证格式不正确");
        }
    }

    public static void notHaveSpecialWord(String word) {
        if (StringUtils.isNotBlank(word)) {
            Pattern p = Pattern.compile(SPECIAL_WORD_REG);
            Matcher m = p.matcher(word);
            if (m.find()) {
                throw new BusinessException(METHOD_ARGUMENT_NOT_VALID.getCode(), word + "包含特殊字符");
            }
        }
    }

    public static void isChineseWord(String word) {
        if (StringUtils.isNotBlank(word)) {
            Pattern p = Pattern.compile(CHINESE_WORD_REG);
            Matcher m = p.matcher(word);
            if (!m.find()) {
                throw new BusinessException(METHOD_ARGUMENT_NOT_VALID.getCode(), word + "有非中文字符");
            }
        }
    }


    public static <T> T function(Supplier<T> supplier, RuntimeException e) {

        if (supplier == null) {
            throw new BusinessException(FUNCTION_NO_HAVE, FUNCTION_NO_HAVE.getMessage());
        }

        try {
            return supplier.get();
        } catch (Exception ex) {

            RuntimeException exception;
            if (e == null) {
                exception = new BusinessException(INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR.getMessage());
            } else {
                exception= e;
            }
            throw exception;
        }
    }

    public static <T> T function(Supplier<T> supplier, Integer errCode, String msg) {

        if (supplier == null) {
            throw new BusinessException(FUNCTION_NO_HAVE, FUNCTION_NO_HAVE.getMessage());
        }

        try {
            return supplier.get();
        } catch (Exception ex) {

            Integer code = errCode;
            if (code == null) {
                code = INTERNAL_SERVER_ERROR.getCode();
            }
            throw new BusinessException(code, msg);
        }
    }

    public static <T> T function(Supplier<T> supplier, String msg) {

        if (supplier == null) {
            throw new BusinessException(FUNCTION_NO_HAVE, FUNCTION_NO_HAVE.getMessage());
        }
        try {
            return supplier.get();
        } catch (Exception ex) {
            throw new BusinessException(INTERNAL_SERVER_ERROR.getCode(), msg);
        }
    }

    public static <T> T function(Supplier<T> supplier) {

        if (supplier == null) {
            throw new BusinessException(FUNCTION_NO_HAVE, FUNCTION_NO_HAVE.getMessage());
        }
        try {
            return supplier.get();
        } catch (Exception ex) {
            throw new BusinessException(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMessage());
        }
    }

}
